﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;
using System.IO.Ports;
using System.Text;
using LightOMator.Color;
using Enough.Connectivity;
using Enough.Connectivity.Seeedstudio;

namespace LightOMator
{


    public class Program
    {

        private static OutputPort _led = new OutputPort(Pins.ONBOARD_LED, false);

        private static PWM _pwmRed = new PWM(PWMChannels.PWM_PIN_D5, frequency_Hz: 1000D, dutyCycle: 1.0, invert: false);
        private static PWM _pwmGreen = new PWM(PWMChannels.PWM_PIN_D6, frequency_Hz: 1000D, dutyCycle: 0, invert: false);
        private static PWM _pwmBlue = new PWM(PWMChannels.PWM_PIN_D9, frequency_Hz: 1000D, dutyCycle: 0, invert: false);

        private static IBinaryConnection _connection;
        private static IColorController _colorController;

        public static void Main()
        {
            SeeedstudioBluetoothShieldConnection btConnection = new SeeedstudioBluetoothShieldConnection();
            btConnection.Initialize(serialPortname: SerialPorts.COM2, bluetoothName: "SeeedBTSlave");
            _connection = btConnection;
            _connection.OnStringReceived += onStringReceived;

            _pwmRed.Start();
            _pwmGreen.Start();
            _pwmBlue.Start();

            _colorController = new StaticColorController(RgbColor.ColorBlue);
            // cycle through colors:
            IColorController lastController = null;
            while (true)
            {
                IColorController controller = _colorController;
                if (controller != lastController)
                {
                    setColor(controller.FirstColor(DateTime.Now.Ticks));
                    lastController = controller;
                }
                else
                {
                    RgbColor color = controller.NextColor(DateTime.Now.Ticks);
                    if (color != null)
                    {
                        setColor(color);
                    }
                }
                Thread.Sleep(10);
            }
        }

        private static void onStringReceived(IBinaryConnection sender, string data)
        {
            string[] values = data.Split('|');
            if (values.Length > 1 && values[0] == "")
            {
                char command = values[1][0];
                if (command == 'c')
                {
                    RgbColor color = new RgbColor(byte.Parse(values[2]), byte.Parse(values[3]), byte.Parse(values[4]));
                    _colorController = new StaticColorController(color);
                    //string responseStr = receivedData + " processed on netduino";
                    //write(responseStr, _serial, addLength: true);
                }
                else if (command == 'f')
                {
                    string fadeModeStr = values[2];
                    FaderController.FadeMode fadeMode;
                    if ("d".Equals(fadeModeStr))
                    {
                        fadeMode = FaderController.FadeMode.DirectFade;
                    }
                    else if ("n".Equals(fadeModeStr))
                    {
                        fadeMode = FaderController.FadeMode.NoFade;
                    }
                    else
                    {
                        fadeMode = FaderController.FadeMode.DarkFade;
                    }
                    int numberOfFades = int.Parse(values[3]);
                    FaderController.Fade[] fades = new FaderController.Fade[numberOfFades];
                    int start = 4;
                    int valuesPerFader = 5;
                    for (int i = 0; i < numberOfFades; i++)
                    {
                        int offset = start + (i * valuesPerFader);
                        RgbColor color = new RgbColor(byte.Parse(values[offset]), byte.Parse(values[offset+1]), byte.Parse(values[offset+2]));
                        int fadeInTimeMs = int.Parse(values[offset+3]);
                        int keepTimeMs = int.Parse(values[offset + 4]);
                        fades[i] = new FaderController.Fade { Color = color, FadeInTimeMs = fadeInTimeMs, FadeOutTimeMs = fadeInTimeMs, KeedOnTimeMs = keepTimeMs };
                    }
                    _colorController = new FaderController { Mode = fadeMode, Fades = fades };
                }
                else if ((command == 'k' || command == 'i') && _colorController is FaderController)
                {
                    FaderController controller = (FaderController)_colorController;
                    int time = int.Parse(values[2]);
                    foreach (FaderController.Fade fade in controller.Fades)
                    {
                        if (command == 'k')
                        {
                            fade.KeedOnTimeMs = time;
                        }
                        else
                        {
                            fade.FadeInTimeMs = time;
                        }
                    }
                }
            }
            else if (data == "on" || data == "off")
            {
                bool ledOn = "on".Equals(data);
                _led.Write(ledOn);
                //write("LED set " + receivedData, _serial, addLength: true);
            }
            else
            {
                _connection.SendString("unknown command: " + data, sendLength: true);
            }
        }


        private static void setColor(RgbColor next)
        {
            _pwmRed.DutyCycle = next.RedDutyCycle;
            _pwmGreen.DutyCycle = next.GreenDutyCycle;
            _pwmBlue.DutyCycle = next.BlueDutyCycle;
        }

    }
}

